#include "calculateFeatures.h"

Features::Features(const char * _aviFileName, const char * _stipPointsFileName, const char * _hogFeatureFileName, const char * _flowFeatureFileName,const char * _motionEnegryFileName,  const char * _featureFileName):aviFileName(_aviFileName),stipPointsFileName(_stipPointsFileName),hogFeatureFileName(_hogFeatureFileName),flowFeatureFileName(_flowFeatureFileName),featureFileName(_featureFileName),motionEnegryFileName(_motionEnegryFileName) 
{
  HOGObjectPtr = new HOG::HOGCache() ;
  stipObjectPtr = new STIP::Stip() ;
  histogramFlowObjectPtr = new HistogramOfFlow(aviFileName.c_str(),stipPointsFileName.c_str(),flowFeatureFileName.c_str()) ;
}
Features::~Features()
{
  if( stipObjectPtr != NULL ) 
    delete stipObjectPtr ;
  if( HOGObjectPtr != NULL )
    delete HOGObjectPtr ;
}
void Features::calculateHogFeature()
{
  cvNamedWindow("source",1) ;
  std::ifstream stipPointsFileStream(stipPointsFileName.c_str());
  std::ofstream featuresFileStream(hogFeatureFileName.c_str());
  if( !stipPointsFileStream.is_open() )
    {
      INFO2("stip file name",stipPointsFileName) ;
      ERROR("can't open the stip stream") ;
      exit(-1) ;
    }
  if( !featuresFileStream.is_open() )
    {
      INFO2("features file name",hogFeatureFileName) ;
      ERROR("can't open the featurs stream");
      exit(-1) ;
    }
  CvCapture * capture = cvCaptureFromFile(aviFileName.c_str()) ;
  if( capture == NULL )
    {
      INFO2("video file name",aviFileName) ;
      ERROR("can't open the video!") ;
      exit(-1) ;
    }
  IplImage * imagePtr = cvQueryFrame(capture);
  int imageNum = 0 ;
  std::vector<cv::Point> pointsList ;
  int indexImage ;
  int sizeList ;
  int addx = HOGObjectPtr->winSize.width>>1;
  int addy = HOGObjectPtr->winSize.height>>1;
  while( stipPointsFileStream >> indexImage )
    {
      stipPointsFileStream >> sizeList ;
      pointsList.resize(sizeList) ;
      for( int index = 0 ; index < sizeList ; ++ index )
	{
	  char temp ;
	  stipPointsFileStream >> temp ;
	  stipPointsFileStream >> pointsList[index].x >> pointsList[index].y ;
	  stipPointsFileStream >> temp ;
	}
      while( imageNum < indexImage )
	{
	  imagePtr = cvQueryFrame(capture) ;
	  imageNum ++ ;
	}
      /*
      INFO2("indexImage",indexImage);
      INFO2("calcualteFeatures pointsSize",sizeList) ;
      for( int index = 0 ; index < sizeList ; ++ index)
	INFO2("Point",pointsList[index]) ;
      */
      IplImage * cc = cvCloneImage(imagePtr);
      stipObjectPtr->drawCircle(cc,pointsList) ;
      cvShowImage("source",cc) ;
      int histWindows = HOGObjectPtr->compute(imagePtr,featuresVector,pointsList) ;
      
      stipObjectPtr->drawCircle(imagePtr,pointsList) ;
      /*
      char imageName[25];
      itoa(imageNum,imageName,30) ;
      INFO2(imageNum,imageName) ;
      strcat(imageName,".jpg") ;
      std::string imageFileName = "../PicResult/" ;
      imageFileName += imageName ;
      cvSaveImage(imageFileName.c_str(),imagePtr) ;
      */
      //      cvShowImage("source",imagePtr) ;
      cvWaitKey(33) ;

      for( int index = 0 ; index < pointsList.size() ; ++ index )
	{
	  featuresFileStream << "# " << imageNum << "\t[" << (pointsList[index].x+addx) << "\t" << (pointsList[index].y + addy)<< "]\n";
	  int begin_index = index*histWindows ;
	  for( int index_feature = 0 ; index_feature < histWindows ; ++ index_feature )
	    featuresFileStream << featuresVector[begin_index+index_feature] << "\t";
	  featuresFileStream << std::endl ;
	}
    }
  cvReleaseCapture(&capture) ;
  featuresFileStream.close() ;
  stipPointsFileStream.close() ;
  cvDestroyWindow("source") ;
}
void Features::getFeaturesFromVideo()
{
  if( access(featureFileName.c_str(),F_OK) == 0 )
    {
      INFO2("features is exist!",featureFileName);
      return ;
    }
  if( access(stipPointsFileName.c_str(),F_OK) == 0 )
    {
      INFO2("stipPointsFile is exist!",stipPointsFileName) ;
    }
  else
    {
      stipObjectPtr->setVideoName(aviFileName.c_str(),stipPointsFileName.c_str()) ;
      stipObjectPtr->calculateSTIP() ;
      INFO2("calculate stip poitns",stipPointsFileName) ;
    }
  calculateHogFeature() ;
  histogramFlowObjectPtr->getFeaturesFromVideo() ;
  combiningFeature() ;
}
// 将hof hog特征合并
void Features::combiningFeature()
{
  std::ifstream hogFileStream(hogFeatureFileName.c_str()) ;
  std::ifstream flowFileStream(flowFeatureFileName.c_str()) ;
  std::ifstream motionEnegryFileStream(motionEnegryFileName.c_str()) ;
  std::ofstream featureFileStream(featureFileName.c_str()) ;

  typedef std::map<int, std::vector<float> > mapType ; 
  int frameIndexHog ;
  char temp ;
  int index ;

#ifdef MEI

  mapType MEIMap ; 
  std::string MEIBuffer ;
  while( getline(motionEnegryFileStream,MEIBuffer) )
    {
      std::istringstream ss(MEIBuffer) ;
      if( MEIBuffer[0] == '#' )
	{
	  ss >> temp >> index ;
	}
      else
	{
	  float value ;
	  MEIMap.insert(make_pair(index,std::vector<float>())) ;
	  while( ss >> value)
	    MEIMap[index].push_back(value) ;
	}
    }

#endif

  mapType HogMap ;
  std::string hogBuffer ;
  cv::Point point ;
  while( getline(hogFileStream,hogBuffer) )
    {
      std::istringstream ss(hogBuffer) ;
      if( hogBuffer[0] == '#' )
	{
	  ss >> temp >> frameIndexHog >> temp >> point.x >> point.y >> temp ;
	  // 建立索引
	  index = frameIndexHog*1000000 + point.x*1000 + point.y ; 
	}
      else
	{
	  float value ;
	  HogMap.insert(make_pair(index,std::vector<float>())) ;
	  while(ss>>value)
	    HogMap[index].push_back(value) ;

#ifdef MEI
	  if( MEIMap.find(frameIndexHog) != MEIMap.end() ) 
	    for( int i = 0 ; i < MEIMap[frameIndexHog].size() ; ++ i )
	      HogMap[index].push_back(MEIMap[frameIndexHog][i]) ;
#endif

	}
    }
#ifdef HOF

  std::string flowBuffer ;
  int frameIndexFlow ;
  while( getline(flowFileStream,flowBuffer) )
    {
      std::istringstream ss(flowBuffer) ;
      if( flowBuffer[0] == '#' ) 
	{
	  ss >> temp >> frameIndexFlow >> temp >> point.x >> point.y >> temp ;
	  index = frameIndexFlow*1000000 + point.x*1000 + point.y ;
	}
      else
	{
	  mapType::iterator iter = HogMap.find(index) ;
	  if( iter == HogMap.end() ) 
	    continue ;
	  featureFileStream << "#\t" << frameIndexFlow << "\t[" << point.x << "\t" << point.y << "]\n" ;
	  for( int index = 0 ; index < iter->second.size() ; ++ index )
	    featureFileStream << iter->second[index] << "\t" ;
	  float value ;
	  while( ss >> value)
	    featureFileStream << value << "\t" ;
	  featureFileStream << std::endl ;
	}
    }
#else
  for(  mapType::iterator iter = HogMap.begin() ; iter != HogMap.end() ; ++ iter )
    {
      int index = iter->first / 1000000 ;
      int x = iter->first / 1000 % 1000 ;
      int y = iter-> first % 1000 ;
      featureFileStream << "#\t" << index << "\t[" << x << "\t" << y << "]\n" ;
      for( int i = 0 ; i < iter->second.size() ; ++ i )
	featureFileStream << iter->second[i] << "\t" ;
      featureFileStream << std::endl ;
    }
#endif
}
